package com.example.lostandfoundsystem.services.common.task;

import cn.hutool.extra.spring.SpringUtil;
import com.example.lostandfoundsystem.services.common.model.TaskHelper;
import gaarason.database.appointment.OrderBy;
import gaarason.database.contract.eloquent.Record;
import gaarason.database.contract.eloquent.RecordList;
import gaarason.database.exception.SQLRuntimeException;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author lucifer
 * @since 2024-07-12-15:36
 */
public class TaskService implements ApplicationListener<ApplicationReadyEvent> {
    private static TaskHelper.Model taskHelperModel;

    //线程池
    private static ExecutorService executor;

    static {
        // 创建工作器
        taskHelperModel = SpringUtil.getBean(TaskHelper.Model.class);
        // 创建线程池
        executor = Executors.newFixedThreadPool(2);
    }

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        // 启动后执行
        System.out.println("finish start and run work");
        loadUnfinishTask();
    }

    private static void loadUnfinishTask() {
        try {
            // 载入没完成的task
            RecordList<TaskHelper, Long> taskHelperList = taskHelperModel.newQuery().whereIn("status", 0, 1).orderBy("id", OrderBy.ASC).get();
            System.out.println("load:" + taskHelperList.count());
            for (Record<TaskHelper, Long> taskHelper : taskHelperList) {
                try {
                    // 加载这个类
                    Class clazz = Class.forName(taskHelper.getEntity().getClazz());
                    String number = taskHelper.getEntity().getNumber();
                    List<String> param = new ArrayList<>(Arrays.asList(taskHelper.getEntity().getParam().split(",")));
                    int now = Integer.parseInt(taskHelper.getEntity().getNow());
                    int max = Integer.parseInt(taskHelper.getEntity().getMax());
                    Object o = null;
                    // 尝试使用各种构造方法创建
                    try {
                        //完全无参创建方法
                        o = clazz.getDeclaredConstructor().newInstance();
                    } catch (NoSuchMethodException e) {
                        try {
                            // 1个参数的构造方法
                            o = clazz.getDeclaredConstructor(String.class).newInstance(number);
                        } catch (NoSuchMethodException e2) {
                            try {
                                // 2个参数的构造方法
                                o = clazz.getDeclaredConstructor(String.class, List.class).newInstance(number, param);
                            } catch (NoSuchMethodException e3) {
                                try {
                                    // 3个参数的构造方法
                                    o = clazz.getDeclaredConstructor(String.class, List.class, int.class).newInstance(number, param, max);
                                } catch (NoSuchMethodException e4) {
                                    try {
                                        // 4个参数的构造方法
                                        o = clazz.getDeclaredConstructor(String.class, List.class, int.class, int.class).newInstance(number, param, now, max);
                                    } catch (NoSuchMethodException e5) {
                                        // 如果还是创建不出来就不管了
                                        e5.printStackTrace();
                                    }
                                }
                            }
                        }
                    }
                    if (o instanceof Task) {
                        // 如果这个o是task类型，那么就可以run它
                        Task task = (Task) o;
                        task.number = number;
                        task.param = param;
                        task.now = now;
                        task.max = max;
                        taskHelperRunTask(taskHelper.getEntity(), task);
                    }
                } catch (ClassNotFoundException | InvocationTargetException |
                         InstantiationException | IllegalAccessException e) {
                    // 有错不管
                    e.printStackTrace();
                }
            }
        } catch (SQLRuntimeException runtimeException) {
            // runtimeException.printStackTrace();
        }
    }

    /**
     * 根据taskHelper进行执行
     * @param taskHelper
     * @param task
     */
    private static void taskHelperRunTask(TaskHelper taskHelper, Task task) {
        task.taskId = String.valueOf(taskHelper.getId());
        task.result = taskHelper.getResult();
        //把任务扔到队列里
        executor.execute(new TaskRunner(task));
//        jobList.add(new TaskRunner(task));
    }

    /**
     * 运行任务
     * @param task
     * @return
     */
    public static String runTask(Task task) {
        Record<TaskHelper, Long> taskHelper = taskHelperModel.newRecord();
        taskHelper.getEntity().setNumber(task.number);
        // 记录运行的类
        taskHelper.getEntity().setClazz(task.getClass().getName());
        taskHelper.getEntity().setNow(String.valueOf(task.now));
        taskHelper.getEntity().setMax(String.valueOf(task.max));
        // 参数转为string分隔
        taskHelper.getEntity().setParam(String.join(",", task.param));
        // task创建时设置运行状态为0
        taskHelper.getEntity().setStatus(String.valueOf(0));
        taskHelper.save();
        // 记录这个任务的任务id
        task.taskId = String.valueOf(taskHelper.getEntity().getId());
        // 把任务扔到队列里
        executor.execute(new TaskRunner(task));
        return task.taskId;
    }

    private static class TaskRunner implements Runnable {
        private Task task;

        public TaskRunner(Task task) {
            this.task = task;
        }

        @Override
        public void run() {
            // 首先执行preRun()，判断能否执行
            boolean hasError = false;
            taskPre(task);
            if (task.preRun()) {
                boolean needRunning;
                do {
                    try {
                        // 可以执行则执行task任务
                        task.run();
                        // 正常执行完成后把needRunning设置为false，即可退出for循环
                        needRunning = false;
                        hasError = false;
                    } catch (Throwable throwable) {
                        needRunning = task.catchError(throwable);
                        //出错过，设置hasError是true
                        hasError = true;
                    }
                } while (needRunning);

            }
            // 执行运行完后的任务
            task.afterRun();
            // 写入运行结束的数据
            taskAfter(task, hasError);
        }
    }

    static void taskPre(Task task) {
        Record<TaskHelper, Long> taskHelper = taskHelperModel.newQuery().find(task.taskId);
        if (taskHelper != null) {
            // 写入相关信息
            taskHelper.getEntity().setNumber(task.number);
            taskHelper.getEntity().setNow(String.valueOf(task.now));
            taskHelper.getEntity().setMax(String.valueOf(task.max));
            // 参数转为string分隔
            taskHelper.getEntity().setParam(String.join(",", task.param));
            taskHelper.getEntity().setResult(task.result);
            // 2为完成
            taskHelper.getEntity().setStatus(String.valueOf(1));
            taskHelper.save();
        }
    }

    static void taskAfter(Task task, boolean hasError) {
        Record<TaskHelper, Long> taskHelper = taskHelperModel.newQuery().find(task.taskId);
        if (taskHelper != null) {
            // 写入相关信息
            taskHelper.getEntity().setNumber(task.number);
            taskHelper.getEntity().setNow(String.valueOf(task.now));
            taskHelper.getEntity().setMax(String.valueOf(task.max));
            // 参数转为string分隔
            taskHelper.getEntity().setParam(String.join(",", task.param));
            taskHelper.getEntity().setResult(task.result);
            if (hasError) {
                taskHelper.getEntity().setStatus(String.valueOf(3));
            } else {
                // 2为完成
                taskHelper.getEntity().setStatus(String.valueOf(2));
            }
            System.out.println("taskAfter");
            taskHelper.save();
        }
    }

    /**
     * 步进
     * @param taskId
     * @param now
     */
    static void taskStep(String taskId, String now) {
        Record<TaskHelper, Long> taskHelper = taskHelperModel.newQuery().find(taskId);
        if (taskHelper != null) {
            taskHelper.getEntity().setNow(now);
            taskHelper.save();
        }
    }
}
